using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Office.Interop.Word;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Threading.Tasks;
using System.Threading;
using Task = System.Threading.Tasks.Task;

namespace ImageToWordWPF
{
    public class WordDocumentGenerator
    {
        // 进度报告委托
        public delegate void ProgressReportHandler(int current, int total, string message);
        public event ProgressReportHandler ProgressReport;

        /// <summary>
        /// 异步创建Word文档 (.NET Framework 4.0 兼容版本)
        /// </summary>
        public Task CreateWordDocumentAsync(List<string> imagePaths, string outputPath, bool showBorders, double cellMargin, CancellationToken cancellationToken = default(CancellationToken))
        {
            return Task.Factory.StartNew(() =>
                CreateWordDocument(imagePaths, outputPath, showBorders, cellMargin, cancellationToken),
                cancellationToken,
                TaskCreationOptions.LongRunning,
                TaskScheduler.Default);
        }

        /// <summary>
        /// 创建Word文档（支持取消和进度报告）
        /// </summary>
        public void CreateWordDocument(List<string> imagePaths, string outputPath, bool showBorders, double cellMargin, CancellationToken cancellationToken = default(CancellationToken))
        {
            Microsoft.Office.Interop.Word.Application wordApp = null;
            Document doc = null;

            try
            {
                // 报告开始进度
                ReportProgress(0, imagePaths.Count, "正在初始化Word应用程序...");

                // 检查取消请求
                cancellationToken.ThrowIfCancellationRequested();

                // 创建Word应用程序实例
                wordApp = new Microsoft.Office.Interop.Word.Application();
                wordApp.Visible = false;

                // 创建新文档
                doc = wordApp.Documents.Add();

                // 设置页面边距
                doc.PageSetup.TopMargin = 72; // 1英寸
                doc.PageSetup.BottomMargin = 72;
                doc.PageSetup.LeftMargin = 72;
                doc.PageSetup.RightMargin = 72;

                ReportProgress(1, imagePaths.Count, "正在处理图片分组...");

                // 按每9张图片分组
                var imageGroups = imagePaths
                    .Select((path, index) => new { Path = path, Index = index })
                    .GroupBy(x => x.Index / 9)
                    .Select(g => g.Select(x => x.Path).ToList())
                    .ToList();

                // 为每组图片创建一页
                for (int pageIndex = 0; pageIndex < imageGroups.Count; pageIndex++)
                {
                    // 检查取消请求
                    cancellationToken.ThrowIfCancellationRequested();

                    ReportProgress(pageIndex + 1, imageGroups.Count, string.Format("正在生成第 {0} 页，共 {1} 页...", pageIndex + 1, imageGroups.Count));

                    // 创建铺满整页的表格
                    CreateFullPageTable(doc, imageGroups[pageIndex], showBorders, cellMargin, cancellationToken);

                    // 如果不是最后一页，插入分页符
                    if (pageIndex < imageGroups.Count - 1)
                    {
                        // 清理表格后的多余段落，然后插入分页符
                        CleanAndInsertPageBreak(doc);
                    }

                    // 让出CPU时间，允许UI更新
                    Thread.Sleep(10);
                    cancellationToken.ThrowIfCancellationRequested();
                }

                ReportProgress(imageGroups.Count, imageGroups.Count, "正在保存文档...");

                // 保存文档
                doc.SaveAs2(outputPath);

                ReportProgress(imageGroups.Count, imageGroups.Count, "文档生成完成！");
            }
            catch (OperationCanceledException)
            {
                ReportProgress(0, 0, "操作已取消");
                throw;
            }
            finally
            {
                // 清理资源
                if (doc != null)
                {
                    try
                    {
                        doc.Close();
                        Marshal.ReleaseComObject(doc);
                    }
                    catch { }
                }

                if (wordApp != null)
                {
                    try
                    {
                        wordApp.Quit();
                        Marshal.ReleaseComObject(wordApp);
                    }
                    catch { }
                }

                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
        }

        private void CreateFullPageTable(Document doc, List<string> imagePaths, bool showBorders, double cellMargin, CancellationToken cancellationToken)
        {
            // 获取当前文档末尾位置
            Range range = doc.Range();
            range.Collapse(WdCollapseDirection.wdCollapseEnd);

            // 创建3x3表格
            Table table = doc.Tables.Add(range, 3, 3);

            // 计算页面尺寸
            float pageWidth = (float)doc.PageSetup.PageWidth - (float)doc.PageSetup.LeftMargin - (float)doc.PageSetup.RightMargin;
            float pageHeight = (float)doc.PageSetup.PageHeight - (float)doc.PageSetup.TopMargin - (float)doc.PageSetup.BottomMargin;

            // 增加缓冲空间，确保表格不跨页
            float bufferSpace = showBorders ? 50f : 40f;
            float availableTableHeight = pageHeight - bufferSpace;

            // 设置表格样式
            if (showBorders)
            {
                table.Borders.Enable = 1;
                table.Borders.OutsideLineStyle = WdLineStyle.wdLineStyleSingle;
                table.Borders.InsideLineStyle = WdLineStyle.wdLineStyleSingle;
                table.Borders.OutsideLineWidth = WdLineWidth.wdLineWidth050pt;
                table.Borders.InsideLineWidth = WdLineWidth.wdLineWidth050pt;
            }
            else
            {
                table.Borders.Enable = 0;
                table.Borders.OutsideLineStyle = WdLineStyle.wdLineStyleNone;
                table.Borders.InsideLineStyle = WdLineStyle.wdLineStyleNone;
            }

            // 设置表格完全铺满页面宽度
            table.PreferredWidthType = WdPreferredWidthType.wdPreferredWidthPoints;
            table.PreferredWidth = pageWidth;
            table.Rows.Alignment = WdRowAlignment.wdAlignRowLeft;

            // 使用严格的行高控制
            float rowHeight = availableTableHeight / 3;
            table.Rows.HeightRule = WdRowHeightRule.wdRowHeightExactly;
            table.Rows.Height = rowHeight;

            // 设置列宽平均分配
            float colWidth = pageWidth / 3;
            for (int i = 1; i <= table.Columns.Count; i++)
            {
                Column col = table.Columns[i];
                col.PreferredWidthType = WdPreferredWidthType.wdPreferredWidthPoints;
                col.PreferredWidth = colWidth;
            }

            // 插入图片到单元格（同步方式，但在后台线程中执行）
            for (int i = 0; i < imagePaths.Count && i < 9; i++)
            {
                cancellationToken.ThrowIfCancellationRequested();
                ProcessImage(table, imagePaths[i], i, colWidth, rowHeight, cellMargin);
            }

            // 清理表格周围的多余内容
            CleanAroundTable(doc, table);
        }

        private void ProcessImage(Table table, string imagePath, int imageIndex, float colWidth, float rowHeight, double cellMargin)
        {
            try
            {
                int row = imageIndex / 3 + 1;
                int col = imageIndex % 3 + 1;

                Cell cell = table.Cell(row, col);

                // 设置单元格属性
                cell.TopPadding = (float)cellMargin;
                cell.BottomPadding = (float)cellMargin;
                cell.LeftPadding = (float)cellMargin;
                cell.RightPadding = (float)cellMargin;
                cell.VerticalAlignment = WdCellVerticalAlignment.wdCellAlignVerticalCenter;

                if (File.Exists(imagePath))
                {
                    using (var img = System.Drawing.Image.FromFile(imagePath))
                    {
                        Range cellRange = cell.Range;
                        cellRange.Text = "";

                        // 插入图片
                        InlineShape shape = cellRange.InlineShapes.AddPicture(imagePath);

                        // 计算可用空间
                        float cellAvailableWidth = colWidth - (float)cellMargin * 2 - 5f;
                        float cellAvailableHeight = rowHeight - (float)cellMargin * 2 - 5f;

                        // 计算图片原始尺寸
                        float imageWidthPoints = (float)(img.Width * 72.0 / img.HorizontalResolution);
                        float imageHeightPoints = (float)(img.Height * 72.0 / img.VerticalResolution);

                        // 只缩小不放大，保持比例
                        float scaleX = cellAvailableWidth / imageWidthPoints;
                        float scaleY = cellAvailableHeight / imageHeightPoints;
                        float scale = Math.Min(Math.Min(scaleX, scaleY), 1.0f);

                        // 应用缩放
                        shape.Width = imageWidthPoints * scale;
                        shape.Height = imageHeightPoints * scale;

                        // 设置对齐
                        cellRange.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphCenter;
                        cellRange.ParagraphFormat.SpaceBefore = 0;
                        cellRange.ParagraphFormat.SpaceAfter = 0;
                        cellRange.ParagraphFormat.LineSpacing = 12f;
                        cellRange.ParagraphFormat.SpaceAfterAuto = 0;
                        cellRange.ParagraphFormat.SpaceBeforeAuto = 0;
                    }
                }
            }
            catch (Exception ex)
            {
                // 处理图片加载错误
                try
                {
                    int row = imageIndex / 3 + 1;
                    int col = imageIndex % 3 + 1;
                    Cell cell = table.Cell(row, col);

                    cell.Range.Text = string.Format("图片加载失败: {0}", Path.GetFileName(imagePath));
                    cell.Range.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphCenter;
                    cell.Range.Font.Size = 10;
                    cell.Range.ParagraphFormat.SpaceBefore = 0;
                    cell.Range.ParagraphFormat.SpaceAfter = 0;
                }
                catch { }
            }
        }

        private void CleanAroundTable(Document doc, Table table)
        {
            try
            {
                Range tableRange = table.Range;

                if (tableRange.Start > 0)
                {
                    Range beforeRange = doc.Range(Math.Max(0, tableRange.Start - 20), tableRange.Start);
                    string beforeText = beforeRange.Text;

                    if (!string.IsNullOrEmpty(beforeText) && !beforeText.Contains("\f"))
                    {
                        string cleanedText = System.Text.RegularExpressions.Regex.Replace(beforeText, @"\r+", "\r");
                        if (cleanedText != beforeText)
                        {
                            beforeRange.Text = cleanedText;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(string.Format("清理表格周围内容时出错: {0}", ex.Message));
            }
        }

        private void CleanAndInsertPageBreak(Document doc)
        {
            try
            {
                Range docEnd = doc.Range();
                docEnd.Collapse(WdCollapseDirection.wdCollapseEnd);

                while (docEnd.Start > 0)
                {
                    Range prevChar = doc.Range(docEnd.Start - 1, docEnd.Start);
                    if (prevChar.Text == "\r")
                    {
                        prevChar.Delete();
                        docEnd = doc.Range();
                        docEnd.Collapse(WdCollapseDirection.wdCollapseEnd);
                    }
                    else
                    {
                        break;
                    }
                }

                docEnd.InsertBreak(WdBreakType.wdPageBreak);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(string.Format("清理并插入分页符时出错: {0}", ex.Message));
                Range range = doc.Range();
                range.Collapse(WdCollapseDirection.wdCollapseEnd);
                range.InsertBreak(WdBreakType.wdPageBreak);
            }
        }

        /// <summary>
        /// 异步打印Word文档 (.NET Framework 4.0 兼容版本)
        /// </summary>
        public Task PrintWordDocumentAsync(string documentPath, CancellationToken cancellationToken = default(CancellationToken))
        {
            return Task.Factory.StartNew(() =>
                PrintWordDocument(documentPath, cancellationToken),
                cancellationToken,
                TaskCreationOptions.LongRunning,
                TaskScheduler.Default);
        }

        public void PrintWordDocument(string documentPath, CancellationToken cancellationToken = default(CancellationToken))
        {
            Microsoft.Office.Interop.Word.Application wordApp = null;
            Document doc = null;

            try
            {
                cancellationToken.ThrowIfCancellationRequested();

                ReportProgress(0, 1, "正在准备打印...");

                wordApp = new Microsoft.Office.Interop.Word.Application();
                wordApp.Visible = false;

                doc = wordApp.Documents.Open(documentPath);

                ReportProgress(1, 1, "正在发送到打印机...");

                doc.PrintOut(Background: false, Append: false, Range: 0,
                    Item: 7, Copies: "1", Pages: "",
                    PageType: 0, PrintToFile: false, Collate: true);

                ReportProgress(1, 1, "打印完成");
            }
            catch (OperationCanceledException)
            {
                ReportProgress(0, 0, "打印已取消");
                throw;
            }
            finally
            {
                if (doc != null)
                {
                    try
                    {
                        doc.Close();
                        Marshal.ReleaseComObject(doc);
                    }
                    catch { }
                }

                if (wordApp != null)
                {
                    try
                    {
                        wordApp.Quit();
                        Marshal.ReleaseComObject(wordApp);
                    }
                    catch { }
                }

                GC.Collect();
                GC.WaitForPendingFinalizers();

                try
                {
                    if (File.Exists(documentPath) && documentPath.Contains("tmp"))
                    {
                        File.Delete(documentPath);
                    }
                }
                catch { }
            }
        }

        private void ReportProgress(int current, int total, string message)
        {
            if (ProgressReport != null)
            {
                ProgressReport(current, total, message);
            }
        }
    }
}